
const { ccclass, property } = cc._decorator;

@ccclass
export default class JellyTweenCases extends cc.Component {
    @property({ tooltip: CC_DEV && '频率（弹跳次数）' })
    public frequency: number = 4;
    @property({ tooltip: CC_DEV && '衰退指数' })
    public decay: number = 2;
    @property({ tooltip: CC_DEV && '效果总时长' })
    public totalTime: number = 1;
    @property({ tooltip: CC_DEV && '下压缩放' })
    public pressScale: number = 0.2;

    scaleTween: cc.Tween = null
    sitTween: cc.Tween = null
    fallTween:cc.Tween=null
    originalScale: number = 0
    originalPos: cc.Vec2 = cc.Vec2.ZERO

    // onLoad () {}
   
    stopAllTween(){
        if(this.scaleTween){
            this.scaleTween.stop()
            this.scaleTween=null
        }
        if(this.sitTween){
            this.sitTween.stop()
            this.sitTween=null
        }
        if(this.fallTween){
            this.fallTween.stop()
            this.fallTween=null
        }
    }

    // update (dt) {}

    scaleTweenServer() {
        if (this.scaleTween) {
            this.scaleTween.stop()
            this.scaleTween = null
        }
        this.originalScale = this.node.scale
        const pressTime = 0.2 * this.totalTime
        const scaleBackTime = this.totalTime * 0.15;    // 缩放至原始大小时长
        const bouncingTime = this.totalTime * 0.65;     // 弹动时长

        // 振幅
        const amplitude = this.pressScale / scaleBackTime;
        this.scaleTween = cc.tween(this.node)
            .repeat(1,
                cc.tween()
                    .to(pressTime, { scaleX: this.originalScale + this.pressScale, scaleY: this.originalScale - this.pressScale }, { easing: 'sineOut' })
                    .to(scaleBackTime, { scaleX: this.originalScale, scaleY: this.originalScale })
                    .to(bouncingTime, {
                        scaleX: {
                            value: this.originalScale,
                            progress: (start: number, end: number, current: number, t: number) => {
                                return end - this.getDifference(amplitude, t);
                            }
                        },
                        scaleY: {
                            value: this.originalScale,
                            progress: (start: number, end: number, current: number, t: number) => {
                                return end + this.getDifference(amplitude, t);
                            }
                        }
                    })
            )
            .start()
    }
    
    /**
    * 获取目标时刻弹性幅度
    * @param amplitude 幅度
    * @param t 进度（0~1）
    */
    private getDifference(amplitude: number, t: number) {
        // 角速度（ω=2nπ）
        const angularVelocity = this.frequency * Math.PI * 2;
        return amplitude * (Math.sin(t * angularVelocity) / Math.exp(this.decay * t) / angularVelocity);
    }


    sitTweenServer(targetPos: cc.Vec2) {
        if (this.sitTween) {
            this.sitTween.stop()
            this.sitTween = null
        }
        this.originalPos = this.node.getPosition()
        this.sitTween = cc.tween(this.node)
            .repeat(1,
                cc.tween()
                    .to(this.totalTime, {
                        position:{
                            value:targetPos,
                            progress:(start: cc.Vec2, end: cc.Vec2, current: number, t: number) => {
                                return  start.add(this.getSitPos(end,t))
                            }
                        }
                    })
            )
            .start()
    }

    private getSitPos(amplitude: cc.Vec2, t: number){
        const angularVelocity = this.frequency * Math.PI * 2;
        return cc.Vec2.ZERO.lerp(amplitude.mul(10),(Math.sin(t * angularVelocity) / Math.exp(this.decay * t) / angularVelocity)) 
    }


    jellyFall(targetPos:cc.Vec2){
        if(this.fallTween){
            this.fallTween.stop()
            this.fallTween=null
        }
        this.originalPos = this.node.getPosition()
        this.sitTween = cc.tween(this.node)
            .repeat(1,
                cc.tween()
                    .to(this.totalTime*0.15,{position:cc.v2(0,0)},{easing:'quartOut'})
                    .to(this.totalTime*0.85, {
                        position:{
                            value:targetPos,
                            progress:(start: cc.Vec2, end: cc.Vec2, current: number, t: number) => {
                                return  start.add(this.getSinglePos(end,t).mul(this.quartOut(t)))
                            }
                        }
                    })
            )
            .start()
    }

    private getSinglePos(amplitude: cc.Vec2, t: number){
        const angularVelocity = this.frequency * Math.PI;
        return cc.Vec2.ZERO.lerp(amplitude.mul(10),Math.abs((Math.sin(t * angularVelocity) / Math.exp(this.decay * t) / angularVelocity)) ) 
    }
    quartOut (k) { return 1 - ( --k * k * k * k ); }
}
